﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Web.UI;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Web.Script.Serialization;

namespace QuickApp.MVCControl.FlexiGrid
{
    /// <summary>
    /// 封装了输出FlexiGrid控件的HTML
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class FlexiGridRenderer<T> : IGridRenderer<FlexiGridSettings<T>> where T : class
    {
        /// <summary>
        /// 输出FlexiGrid控件的HTML
        /// </summary>
        /// <param name="data">表格类型</param>
        /// <returns>HTML格式的字符串</returns>
        public string Render(FlexiGridSettings<T> data)
        {
            // 如果表格ID没有指定，则自动生成表格ID（Guid.NewGuid()）
            var gridId = string.IsNullOrEmpty(data.GridId)
                               ? string.Format("FlexiGrid_{0}", Guid.NewGuid().ToString("N"))
                               : data.GridId;

            using (var sw = new StringWriter())
            {
                using (var htmlWriter = new HtmlTextWriter(sw))
                {
                    // 创建一个隐藏的Table元素
                    htmlWriter.AddStyleAttribute(HtmlTextWriterStyle.Display, "none");
                    htmlWriter.AddAttribute(HtmlTextWriterAttribute.Id, gridId);
                    htmlWriter.AddAttribute(HtmlTextWriterAttribute.Class, "flexigrid");
                    htmlWriter.RenderBeginTag(HtmlTextWriterTag.Table);
                    htmlWriter.RenderEndTag();
                    htmlWriter.WriteLine();

                    // 创建javascript的代码片段
                    htmlWriter.AddAttribute(HtmlTextWriterAttribute.Type, @"text/javascript");
                    htmlWriter.RenderBeginTag(HtmlTextWriterTag.Script);
                    htmlWriter.Write(GenerateFlexiGridOptions(data));
                    htmlWriter.RenderEndTag();
                    htmlWriter.WriteLine();
                }

                return sw.ToString();
            }
        }

        /// <summary>
        /// 生成FlexiGrid的配置信息
        /// </summary>
        /// <param name="data">表格类型</param>
        /// <returns>FlexiGrid配置信息</returns>
        private string GenerateFlexiGridOptions(FlexiGridSettings<T> data)
        {
            var sb = new StringBuilder();
            // 生成列配置信息
            sb.AppendLine("$(document).ready(function () { ");
            if (!string.IsNullOrEmpty(data.GridId))
            {
                sb.AppendLine("$(\"#" + data.GridId + "\").flexigrid({");
            }
            else
            {
                sb.AppendLine("$(\"table.flexigrid\").flexigrid({");
            }

            #region 基本配置信息
            if (!string.IsNullOrEmpty(data.ActionUrl))
                sb.AppendFormat("url:'{0}',", data.ActionUrl).AppendLine();

            if (!string.IsNullOrEmpty(data.FormActionUrl))
                sb.AppendFormat("formurl:'{0}',", data.FormActionUrl).AppendLine();

            if (data.EnablePager)
                sb.AppendLine("usepager:true,");

            if (data.EnableAutoLoad)
                sb.AppendLine("autoload:true,");

            if (!string.IsNullOrWhiteSpace(data.GridHeight))
                sb.AppendFormat("height:{0},", data.GridHeight).AppendLine();
            else
                sb.AppendLine("height:document.documentElement.clientHeight-111,");

            if (string.IsNullOrWhiteSpace(data.GridWidth))
            {
                data.Width("document.documentElement.clientWidth - 2");
            }
            sb.AppendFormat("width:{0},", data.GridWidth).AppendLine();

            if (!string.IsNullOrEmpty(data.GridTitle))
                sb.AppendFormat("title:'{0}',", data.GridTitle).AppendLine();

            if (data.GridDataType != FlexiGridDataType.JSON)
                sb.AppendLine("dataType:'xml',");

            #region 排序字段
            if (!string.IsNullOrEmpty(data.DefaultSortField))
            {
                sb.AppendFormat("sortname:'{0}',", data.DefaultSortField).AppendLine();
                sb.AppendFormat("sortorder:'{0}',", data.DefaultSortOrder.ToString().ToLower()).AppendLine();
            }
            else // 从列信息中自动推算排序字段
            {
                var column = data.GridColumns.FirstOrDefault(col => col.FieldName.ToLower() == "seqno");
                if (column != null) // 判断是否有排序号字段（SeqNo）
                {
                    sb.AppendFormat("sortname:'{0}',", column.FieldName).AppendLine();
                    sb.AppendFormat("sortorder:'{0}',", FlexiGridSortOrder.Asc.ToString().ToLower()).AppendLine();
                }
                else
                {
                    column = data.GridColumns.FirstOrDefault(col => col.FieldName.ToLower() == "updatedate");
                    if (column != null) // 判断是否有最后更新时间字段（UpdateDate）
                    {
                        sb.AppendFormat("sortname:'{0}',", column.FieldName).AppendLine();
                        sb.AppendFormat("sortorder:'{0}',", FlexiGridSortOrder.Desc.ToString().ToLower()).AppendLine();
                    }
                    else
                    {
                        column = data.GridColumns.FirstOrDefault(col => col.ColumnSettings.ColumnIsKey);
                        if (column != null) // 判断是否有主键字段（如 Id）
                        {
                            sb.AppendFormat("sortname:'{0}',", column.FieldName).AppendLine();
                            sb.AppendFormat("sortorder:'{0}',", FlexiGridSortOrder.Asc.ToString().ToLower()).AppendLine();
                        }
                    }
                }
            }
            #endregion

            if (data.GridDataType != FlexiGridDataType.JSON)
                sb.AppendLine("dataType:'xml',");

            if (data.EnableRecordsPerPage)
                sb.AppendLine("useRp:true,");

            if (data.EnableTableToggleButton)
                sb.AppendLine("showTableToggleBtn:true,");

            if (data.EnableShowCheckBox)
                sb.AppendLine("showcheckbox:true,");

            if (data.EnableSelectedOnClick)
                sb.AppendLine("selectedonclick:true,");

            if (data.PageSize > 0)
                sb.AppendFormat("rp:{0},", data.PageSize).AppendLine();

            if (!string.IsNullOrEmpty(data.GridRowChecked))
                sb.AppendFormat("onrowchecked:'{0}',", data.GridRowChecked).AppendLine();

            if (data.GridExtParam != null && data.GridExtParam.Count > 0)
                sb.AppendFormat("extParam:{0},", GetExtParams(data.GridExtParam)).AppendLine();

            // 暂时先加上，后续需要通过属性控制
            sb.AppendLine("rowbinddata:true,");

            var c = data.GridColumns.Where(col => col.ColumnSettings.ColumnIsQuickSearch).ToList();
            var itemCount = c.Count;
            if (itemCount > 0)
            {
                string searchtext = "请输入";
                for (int i = 0; i < itemCount; i++)
                {
                    searchtext += c[i].ColumnSettings.ColumnTitle;
                    if (i == itemCount - 2)
                    {
                        searchtext += "或者";
                    }
                    else if (i < itemCount - 2)
                    {
                        searchtext += "、";
                    }
                }
                sb.AppendFormat("searchtext:'{0}',", searchtext).AppendLine();

                var qtype = string.Join(",", c.Select(col => col.FieldName).ToArray());
                sb.AppendFormat("qtype:'{0}',", qtype).AppendLine();
            }
            #endregion

            #region 检索项配置信息
            // 生成检索的配置信息
            sb.AppendLine("searchitems:[");
            int count = 0;
            var searchColumn = data.GridColumns.Where(col => col.ColumnSettings.ColumnIsAdvancedSearch);
            int totalCount = searchColumn.Count();
            foreach (FlexiGridColumn column in searchColumn)
            {
                count++;
                sb.AppendFormat("{{ display: '{0}', name: '{1}' }}", column.ColumnSettings.ColumnTitle, column.FieldName);

                if (count < totalCount)
                {
                    sb.AppendLine(",");
                }
            }

            sb.AppendLine();
            sb.AppendLine("],");
            #endregion

            #region 按钮配置信息
            // 生成按钮信息
            sb.AppendLine("buttons:[");
            count = 0;
            totalCount = data.GridButtons.Count;
            foreach (FlexiGridButton button in data.GridButtons)
            {
                count++;
                sb.Append("{");
                if (!string.IsNullOrEmpty(button.ButtonTitle))
                    sb.AppendFormat("displayname:'{0}',", button.ButtonTitle);
                if (!string.IsNullOrEmpty(button.ButtonToolTip))
                    sb.AppendFormat("title:'{0}',", button.ButtonToolTip);
                if (button.ButtonType != 0)
                    sb.AppendFormat("bclass:'{0}',", button.ButtonType.ToString());
                if (!string.IsNullOrEmpty(button.ButtonActionUrl))
                    sb.AppendFormat("url:'{0}',", button.ButtonActionUrl);
                if (button.ButtonOptions != null)
                    sb.AppendFormat("options:{0},", new JavaScriptSerializer().Serialize(button.ButtonOptions));
                if (!string.IsNullOrEmpty(button.ButtonOnPress))
                    sb.AppendFormat("onpress:{0},", button.ButtonOnPress);

                sb.AppendFormat("name:'{0}'", button.ButtonName).Append("}");
                if (count < totalCount)
                {
                    sb.AppendLine(",");
                }
            }
            sb.AppendLine();
            sb.AppendLine("],");
            #endregion

            #region 过滤参数配置信息
            #endregion

            #region 列配置信息
            sb.AppendLine("colModel:[");
            count = 0;
            totalCount = data.GridColumns.Count;
            foreach (FlexiGridColumn column in data.GridColumns)
            {
                count++;
                // 处理枚举列信息，增加枚举文本信息列
                if (!string.IsNullOrEmpty(column.ColumnSettings.ColumnEnumKey))
                {
                    sb.AppendLine(GetEnumTextColumn(column));
                }

                sb.Append("{");
                if (!string.IsNullOrEmpty(column.FieldName))
                    sb.AppendFormat("name:'{0}',", column.FieldName);
                if (!IsAutoColumn(column))
                    sb.AppendFormat("width:{0},", column.ColumnSettings.ColumnWidth);
                else
                    sb.AppendFormat("width:{0},", GetAutoColumnWidth(data));
                if (column.ColumnSettings.ColumnIsKey)
                    sb.Append("iskey:true,");
                if (column.ColumnSettings.ColumnSortable)
                    sb.Append("sortable:true,");
                // 设置表头标题的对齐方式
                sb.AppendFormat("align:'{0}',", column.ColumnSettings.ColumnHeaderAlignment.ToString());
                sb.AppendFormat("contentalign:'{0}',", column.ColumnSettings.ColumnAlignment.ToString());

                if (column.ColumnSettings.ColumnHidden)
                    sb.Append("hide:true,");
                if (column.ColumnSettings.ColumnToggle)
                    sb.Append("hide:true,");

                if (!string.IsNullOrEmpty(column.ColumnSettings.ColumnTemplate)
                    || !string.IsNullOrEmpty(column.ColumnSettings.ColumnJavascript))
                {
                    sb.AppendLine("process:function(value,id,row){");
                    //sb.AppendLine("debugger;");
                    sb.AppendLine("var cell = $('<span>'+value+'</span>');");
                    if (!string.IsNullOrEmpty(column.ColumnSettings.ColumnTemplate))
                    {
                        sb.AppendFormat("cell.html(\"\").append('{0}',row);",
                                        column.ColumnSettings.ColumnTemplate.Trim()
                                        .Replace("\\'", "'")
                                        .Replace("'", "\\\\\\'"));
                    }
                    sb.AppendFormat(";cell.html({0});", column.ColumnSettings.ColumnJavascript);
                    sb.AppendLine("; return cell.html().replace(/\\\\'/g,\"'\");");
                    sb.AppendLine("},");
                }

                if (!string.IsNullOrEmpty(column.ColumnSettings.ColumnProcess))
                    sb.AppendFormat("process:{0},", column.ColumnSettings.ColumnProcess);

                sb.AppendFormat("display:'{0}'", column.ColumnSettings.ColumnTitle).Append("}");
                if (count < totalCount)
                {
                    sb.AppendLine(",");
                }
            }

            sb.AppendLine();
            sb.AppendLine("]");
            #endregion

            sb.AppendLine("});").AppendLine("});");
            return sb.ToString();
        }

        /// <summary>
        /// 获取枚举文本的信息列
        /// </summary>
        /// <param name="column">列信息</param>
        /// <returns></returns>
        private string GetEnumTextColumn(FlexiGridColumn column)
        {
            var sb = new StringBuilder();
            if (!string.IsNullOrEmpty(column.ColumnSettings.ColumnEnumKey))
            {
                sb.Append("{");
                if (!string.IsNullOrEmpty(column.FieldName))
                    sb.AppendFormat("name:'{0}',", column.FieldName + DWZSysConstant.FLEXIGRID_COLUMN_ENUM_KEY_SEPARATOR + column.ColumnSettings.ColumnEnumKey);
                if (!string.IsNullOrWhiteSpace(column.ColumnSettings.ColumnWidth))
                    sb.AppendFormat("width:{0},", column.ColumnSettings.ColumnWidth);
                if (column.ColumnSettings.ColumnIsKey)
                    sb.Append("iskey:true,");
                if (column.ColumnSettings.ColumnSortable)
                    sb.Append("sortable:true,");
                // 设置表头标题的对齐方式
                sb.AppendFormat("align:'{0}',", column.ColumnSettings.ColumnHeaderAlignment.ToString());
                sb.AppendFormat("contentalign:'{0}',", column.ColumnSettings.ColumnAlignment.ToString());

                if (column.ColumnSettings.ColumnToggle)
                    sb.Append("hide:true,");
                //if (!string.IsNullOrEmpty(column.ColumnSettings.ColumnJavascript))
                //    sb.AppendFormat("process:{0},", column.ColumnSettings.ColumnJavascript);

                if (!string.IsNullOrEmpty(column.ColumnSettings.ColumnTemplate)
                    || !string.IsNullOrEmpty(column.ColumnSettings.ColumnJavascript))
                {
                    sb.AppendLine("process:function(value,id,row){");
                    sb.AppendLine("var cell = $('<span>'+value+'</span>');");
                    if (!string.IsNullOrEmpty(column.ColumnSettings.ColumnTemplate))
                    {
                        //sb.AppendFormat("cell.html(\"\").append('{0}'.replace(\"\'\",\"'\"),row);",
                        //                column.ColumnSettings.ColumnTemplate.Trim());
                        sb.AppendFormat("cell.html(\"\").append('{0}',row);",
                                        column.ColumnSettings.ColumnTemplate.Trim()
                                        .Replace("\\'", "'")
                                        .Replace("'", "\\\\\\'"));
                    }
                    sb.AppendLine(column.ColumnSettings.ColumnJavascript);
                    sb.AppendLine("; return cell.html();");
                    sb.AppendLine("},");
                }

                sb.AppendFormat("display:'{0}'", column.ColumnSettings.ColumnTitle).Append("},");
            }
            return sb.ToString();
        }

        /// <summary>
        /// 获取外部参数的字符串
        /// </summary>
        /// <param name="dic"></param>
        /// <returns></returns>
        private string GetExtParams(IDictionary<string, object> dic)
        {
            //  [{ name: "parentId", value: data.value}]
            StringBuilder sb = new StringBuilder("[");
            foreach (var key in dic.Keys)
            {
                sb.Append("{");

                // 如果包含 '$ 等字符则为js语句
                if (dic[key].ToString().Contains("'") || dic[key].ToString().Contains("$"))
                {
                    sb.AppendFormat(" name: '{0}', value: {1} ", key, dic[key]);
                }
                else
                {
                    sb.AppendFormat(" name: '{0}', value: '{1}' ", key, dic[key]);
                }
                sb.Append("},");
            }
            return sb.ToString().TrimEnd(',') + "]";
        }

        /// <summary>
        /// 获取自适应的计算方法
        /// </summary>
        /// <returns></returns>
        private string GetAutoColumnWidth(FlexiGridSettings<T> data)
        {
            string js = data.GridWidth;

            var count = data.GridColumns.Where(c => IsAutoColumn(c)).Count();
            if (count > 1)
                throw new Exception("自适应列只能有一列，请设置列宽！");

            foreach (FlexiGridColumn column in data.GridColumns)
            {
                // 排除隐藏列，如果是因为枚举列而隐藏值的列除外
                if ((!column.ColumnSettings.ColumnHidden || !string.IsNullOrEmpty(column.ColumnSettings.ColumnEnumKey))
                    && !IsAutoColumn(column))
                {
                    js += "-" + column.ColumnSettings.ColumnWidth + "-" + "10"; // 10 为每个显示列的偏移量
                }
            }

            // grid的其他宽度 如checkbox列（25），滚动条（30）等偏移量
            if (data.EnableShowCheckBox)
            {
                js += "-" + "55";
            }
            else
            {
                js += "-" + "30";
            }

            return js;
        }

        private bool IsAutoColumn(FlexiGridColumn column)
        {
            return column.ColumnSettings.ColumnWidth.ToLower() == "auto";
        }
    }
}
